package cn.wgx.module.base.web;

import cn.wgx.module.base.entity.BaseEntity;
import cn.wgx.commons.util.BaseLogger;
import cn.wgx.commons.util.DateUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.github.pagehelper.Page;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.beans.PropertyEditorSupport;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.*;


public class BaseController extends BaseLogger {

    public final static List emptyList = new ArrayList<>();

    private final static BlankObject blankObject = new BlankObject();

    private static class BlankObject {}

    static {
        //解决fastjson循环引用问题
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    }
    /**
     * 默认空间
     * @param p
     * @return
     */
    @ApiIgnore()
    @ResponseBody
    @RequestMapping(value = "{p}", method = {RequestMethod.GET,RequestMethod.POST})
    public Map<String, Object> defaultUrl(@PathVariable String p, HttpServletRequest request, HttpSession httpSession){
        Map<String, Object> map = getInitMap();
        if("test1".equals(p)){
            httpSession.setAttribute("testFlag","1");
            map.put("res", "打开测试模式");
            map.put("success", true);
            Object o = httpSession.getAttribute("user");
        }else{
            return returnErrorMap("没找到接口.");
        }
        return map;
    }


    /**
     * 自定义提交参数转换
     * @param binder
     * @throws Exception
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) throws Exception {

        //日期格式转换,LONG转Date
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (text instanceof String) {
                    setValue(DateUtils.parseDate(text));
                }
            }
//			@Override
//			public String getAsText() {
//				Object value = getValue();
//				return value != null ? DateUtils.formatDateTime((Date)value) : "";
//			}
        });

        //解决带下划线参数无法接受问题. 例如: _param, _starDate
        binder.setFieldMarkerPrefix(null);
    }


    protected Map<String, Object> getInitMap(){
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 0);
        map.put("msg", "操作成功!");
//        map.put("count", 0);
        map.put("data", blankObject);
        map.put("success", true);
        return map;
    }

    public Map<String, Object> returnData(Object o){
        return returnData(o, null, null,null);
    }

    public Map<String, Object> returnData(Object o, String key){
        return returnData(o, null, null,key);
    }

    public Map<String, Object> returnData(Object o, Map map){
        return returnData(o, null, map,null);
    }

    public Map<String, Object> returnData(Page page , Object o){
        return returnData(o, page, null,null);
    }

    public Map<String, Object> returnData(Object o , Page page, Map map, String key){
        if(map == null) {
           map = getInitMap();
        }
        if(null == o){
            o = blankObject;
        }else if(o instanceof BaseEntity){
            BaseEntity oo = (BaseEntity)o;
            if(oo.isUpdate() && oo.get_result() != null){
                //o = blankObject;
                map.put("result", oo.get_result());
            }
        }
        if(key == null){
            map.put("data", o);
        }else{
            map.put(key, o);
        }
        if(page != null){
            map.put("count", page.getTotal());
            map.put("pages", page.getPages());
            map.put("pageNum", page.getPageNum());
        }else{
            if(o instanceof Collection){
                map.put("count",((Collection)o).size());
            }
        }
        return map;
    }

    protected Map<String, Object> returnErrorMap(String errorMsg){
        return returnErrorMap(errorMsg, null, null);
    }
    protected Map<String, Object> returnErrorMap(String errorMsg, Integer code){
        return returnErrorMap(errorMsg, code, null);
    }
    protected Map<String, Object> returnErrorMap(String errorMsg, Map<String, Object> map){
        return returnErrorMap(errorMsg,null, map);
    }

    protected Map<String, Object> returnErrorMap(String errorMsg, Integer code, Map<String, Object> map){
        if(map == null) {
            map = getInitMap();
        }
        map.put("msg", errorMsg == null ? "error" : errorMsg);
        map.put("code", code == null ? 0 : code);
        map.put("status", -1);
        map.put("success", false);
        return map;
    }



    //测试方法，打印所有提交参数
    protected void printRequestParam(HttpServletRequest httpServletRequest) {
        if(logger.isDebugEnabled()){
            logger.debug("\n----------------------------------------------");
            logger.debug("Method = " + httpServletRequest.getMethod() + "--"
                    + "QueryString = " + httpServletRequest.getQueryString());
            String body = readAsChars(httpServletRequest);
            logger.debug("body = " + body);
            httpServletRequest.getParameterMap().forEach((k, v) -> {
                if (v.length == 1) {
                    logger.debug(k + " = " + v[0]);
                } else {
                    for (String vv : v) {
                        logger.debug(k + " = " + vv);
                    }
                }

            });
            logger.debug("----------------------------------------------\n");
        }
    }

    protected static String readAsChars(HttpServletRequest request) {

        BufferedReader br = null;
        StringBuilder sb = new StringBuilder("");
        try {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}
